use crate::models::User;
use crate::templates::LoginTemplate; // 引用之前定义的模板结构
use axum::{
    extract::{Form, State},
    response::{IntoResponse, Redirect},
};
use bcrypt::{DEFAULT_COST, hash, verify};
use chrono::Local;
use serde::Deserialize;
use sqlx::{Pool, Postgres};
use tower_sessions::Session; // <--- 确保引入了 Local

// --- 表单数据结构 ---

#[derive(Deserialize)]
pub struct LoginForm {
    username: String,
    password: String,
}

#[derive(Deserialize)]
pub struct RegisterForm {
    username: String,
    password: String,
    email: String,
    intro: String,
}

// --- Handlers ---

// 1. GET /login - 渲染登录页面
pub async fn login_page() -> impl IntoResponse {
    LoginTemplate { error: None }
}

// 2. POST /login - 处理登录提交
pub async fn login_action(
    State(pool): State<Pool<Postgres>>,
    session: Session,
    Form(form): Form<LoginForm>,
) -> impl IntoResponse {
    // 查询用户
    let user_result = sqlx::query_as::<_, User>("SELECT * FROM \"user\" WHERE name = $1")
        .bind(&form.username)
        .fetch_optional(&pool)
        .await
        .unwrap_or(None);

    match user_result {
        Some(user) => {
            // 验证密码 hash
            let valid = verify(&form.password, &user.password).unwrap_or(false);
            if valid {
                // 登录成功：写入 Session
                session.insert("user_id", user.id).await.unwrap();
                session.insert("username", user.name).await.unwrap();

                // 更新最后登录时间
                let _ =
                    sqlx::query("UPDATE \"user\" SET login_date = CURRENT_TIMESTAMP WHERE id = $1")
                        .bind(user.id)
                        .execute(&pool)
                        .await;

                return Redirect::to("/").into_response();
            }
        }
        None => {} // 用户不存在
    }

    // 登录失败：返回带错误信息的页面
    LoginTemplate {
        error: Some("用户名或密码错误".to_string()),
    }
    .into_response()
}

// 3. POST /register - 处理注册提交
pub async fn register_action(
    State(pool): State<Pool<Postgres>>,
    Form(form): Form<RegisterForm>,
) -> impl IntoResponse {
    // 1. 查重
    let exists: Option<i32> = sqlx::query_scalar("SELECT id FROM \"user\" WHERE name = $1")
        .bind(&form.username)
        .fetch_optional(&pool)
        .await
        .unwrap_or(None);

    if exists.is_some() {
        return LoginTemplate {
            error: Some("该用户名已被注册".to_string()),
        }
        .into_response();
    }

    // 2. 密码加密
    let hashed_pwd = match hash(&form.password, DEFAULT_COST) {
        Ok(h) => h,
        Err(_) => {
            return LoginTemplate {
                error: Some("密码处理失败".to_string()),
            }
            .into_response();
        }
    };

    // 3. 插入数据库
    // 【关键修改】使用紧凑的单行 SQL，确保 $$1,$$2 等符号中间绝对没有空格
    let sql = "INSERT INTO \"user\" (name, password, email, intro, register_date) VALUES ($1, $2, $3, $4, $5)";

    // 打印 SQL 方便调试 (运行成功后可删除)
    // println!("正在执行 SQL: {}", sql);

    let result = sqlx::query(sql)
        .bind(&form.username) // $1
        .bind(hashed_pwd) // $2
        .bind(&form.email) // $3
        .bind(&form.intro) // $4
        .bind(Local::now().naive_local()) // $5
        .execute(&pool)
        .await;

    match result {
        Ok(_) => LoginTemplate {
            error: Some("注册成功！请登录。".to_string()),
        }
        .into_response(),
        Err(e) => {
            // 打印完整错误堆栈
            println!("❌ 数据库错误详情: {:?}", e);
            LoginTemplate {
                error: Some(format!("系统错误 (DB): {}", e)),
            }
            .into_response()
        }
    }
}

// 4. GET /logout - 退出登录
pub async fn logout_handler(session: Session) -> impl IntoResponse {
    session.flush().await.unwrap();
    Redirect::to("/login")
}
